package com.klst.opennlp

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

import groovy.util.logging.Log4j
import opennlp.tools.dictionary.Dictionary
import opennlp.tools.sentdetect.SentenceDetector
import opennlp.tools.sentdetect.SentenceDetectorFactory
import opennlp.tools.sentdetect.SentenceDetectorFactoryTest;
import opennlp.tools.sentdetect.SentenceDetectorME
import opennlp.tools.sentdetect.SentenceModel
import opennlp.tools.sentdetect.SentenceSample
import opennlp.tools.sentdetect.SentenceSampleStream
import opennlp.tools.util.InputStreamFactory
import opennlp.tools.util.ObjectStream
import opennlp.tools.util.PlainTextByLineStream
import opennlp.tools.util.TrainingParameters

@Log4j // for Log4J
class SentenceDetectorTrainer extends Script {

  SentenceDetectorTrainer() {
    super()
    log.debug 'ctor()'
  }

  static Dictionary loadAbbDictionary() throws IOException {
    String testDictionary = "Mr. \n Mrs. \n Inc. \n Co. \n jun. \n St. \n tel. \n Nr. \n geb. \n Dr. \n Prof. \n usw. \n etc. \n sog. \n ca. \n bzw. \n Str. \n incl. \n Chr."
    String monateDe = "\n Jan. \n Feb. \n Mar. \n Apr. \n Mai. \n Jun. \n Jul. \n Aug. \n Sep. \n Okt. \n Nov. \n Dez. "
    String monateEn = "\n                                 May.                                 \n Oct.         \n Dec. "
    // was ist mit z.B. z.Zt. z.T. d.h. u.a. Mrd. Mio. Kap. Art. Az. S. v.Chr. (römische Zahlen) e.V.?
    return Dictionary.parseOneEntryPerLine(new StringReader(testDictionary+monateDe+monateEn))
  }
    
  SentenceModel sentenceModel
  
  /* 
   * liefert SentenceModel und die Serialisierung bin 
   */
  def train = { file, bin, languageCode="de" ->
    log.debug "let's train ... "
    
    TrainingParameters trainingParameters = TrainingParameters.defaultParams()
//    trainingParameters.put(TrainingParameters.CUTOFF_PARAM, Integer.toString(3))
    trainingParameters.serialize(System.out)
    Dictionary abbreviationDictionary = loadAbbDictionary()
    log.debug "abbreviationDictionary=" + abbreviationDictionary.asStringSet()
    boolean useTokenEnd = false
    char[] eosCharacters = opennlp.tools.sentdetect.lang.Factory.defaultEosCharacters; // es gibt auch eine groovy.util.Factory! 
    SentenceDetectorFactory sdFactory = new SentenceDetectorFactory(languageCode, useTokenEnd, abbreviationDictionary, eosCharacters)
    
    InputStreamFactory inputStreamFactory = new TigerInputStreamFactory(file)
    ObjectStream<String> lineStream = new PlainTextByLineStream(inputStreamFactory, opennlp.tools.cmdline.SystemInputStreamFactory.encoding().name())
    
    ObjectStream<SentenceSample> sampleStream = new SentenceSampleStream(lineStream)
    
    try {
      // wieso markiert das eclipse als deprecated???
      sentenceModel = opennlp.tools.sentdetect.SentenceDetectorME.train(languageCode, sampleStream, sdFactory, trainingParameters)
    } catch (Exception e) {
      e.printStackTrace();
    }
    sentenceModel.serialize(bin)   
    return sentenceModel
  }
  
  def minitest = { sentencesInput = "I am hungry. I am Mr. Bean. A good sentence." , expRes = 3 ->
    log.debug "minitest ... "
    
    // zeige, was Du kannst:
    SentenceDetector sentenceDetector = new SentenceDetectorME(sentenceModel)
    
    def sentences = null
    if(sentencesInput.getClass() == File) {
      InputStream fis = new FileInputStream(sentencesInput)
      //log.info new InputStreamReader(fis)
      def ss = new SentenceSampleStream(new PlainTextByLineStream(new InputStreamReader(fis)))
      def ssi = ss.read().toString()
      log.debug ssi
      sentences = sentenceDetector.sentDetect(ssi)
    } else {
      sentences = sentenceDetector.sentDetect(sentencesInput)
    }
  
    log.info "sentences="+sentences + " "+sentences.size()+" Sätze. "+expRes+" sind es!"
    return sentences
  }

  private static String RESOURCES_DIR = "src/test/resources/opennlp/"
  private static final String KORPUS = "tiger_release_aug07.corrected.16012013" 
//  private static final String KORPUS = "tiger-mini"
  private static final String KORPUS_XML = SentenceDetectorTrainer.KORPUS + '.xml'
  private static final String KORPUS_TXT = SentenceDetectorTrainer.KORPUS + '.txt'
  private static final String KORPUS_BIN = SentenceDetectorTrainer.KORPUS + '.bin'
    
  @Override
  public Object run() {
    log.setLevel(org.apache.log4j.Level.INFO); // default ist INFO
    log.debug "let's run ... "
    
    File txtFile = new File( RESOURCES_DIR + KORPUS_TXT )
    OutputStream trained = new FileOutputStream(new File( RESOURCES_DIR + KORPUS_BIN ))
    
    long past = System.currentTimeMillis()
//    sentenceModel = train(txtFile,trained)
    sentenceModel = train(RESOURCES_DIR + KORPUS_XML,trained)
    long now = System.currentTimeMillis();
    log.info "input: "+KORPUS_XML + " Time taken: " + (now - past) + " ms"

    /* Quelle: http://de.wikipedia.org/wiki/Wolgograd , 6 Sätze
Die Gegend um Wolgograd war aufgrund ihrer geographischen Lage an der Landenge zwischen Wolga und Don schon im Altertum eine wichtige Handelsroute. 
Hier siedelten im 5. Jahrhundert v. Chr. Skythen. 
Im 8. und 9. Jahrhundert gehörte das Gebiet zum Reich der Chasaren, im 11. und 12. Jahrhundert hielten sich hier verschiedene Stämme und Horden auf, unter anderen die Polovcer oder die Goldene Horde, die etwa 50 km östlich von Wolgograd, am Fluss Achtuba, mit der Stadt Snamensk eines ihrer Zentren errichtete und Wolgograd seit dem Mongolensturm im 13. Jahrhundert beherrschte. 
Die Anfänge des russischen Wolgograds sind nicht näher beleuchtet. 
Als offizielles Gründungsdatum gilt aber der 2. Juli 1589, als die Stadt als Festung gegründet wurde, die Russland vor den Nomaden aus dem Süden schützen sollte. 
Die ursprüngliche Bezeichnung der Stadt ist Zarizyn (Царицын), aus dem Tatarischen sari su (gelbes Wasser) abgeleitet.  

    Quelle: http://de.wikipedia.org/wiki/Abk%C3%BCrzung , 9 Sätze
Die Abkürzungsweise mit Punkten, aber ohne Leerzeichen, ist veraltet. 
Es gibt aber drei Sonderfälle, in welchen dies weiterhin zulässig ist.
Sonderfall: Bei der Verwendung einer Festbreitenschrift (wie etwa bei einer Schreibmaschine) darf das Leerzeichen bei Abkürzungen entfallen. 
Bei der Verwendung einer Proportionalschrift gilt das fehlende Leerzeichen hingegen als falsch.
Beispiele: z.B., d.h., s.o., aber: z. B., d. h., s. o.
Sonderfall: Bei eingebürgerten Abkürzungen, die aus allgemeiner Gewohnheit oder aus Marketinggründen nicht der aktuellen Abkürzungsschreibweise angepasst wurden.
Beispiele: F.A.Z.
Sonderfall: Österreich; gemäß ÖNORM waren bei manchen Abkürzungen, wie jener von „zum Beispiel“, auch folgende Schreibweisen korrekt: zB und z.B. 
Nach der neuesten Ausgabe muss es jedoch so geschrieben werden: z. B.
     */
    String Bsp6 = "Die Gegend um Wolgograd war aufgrund ihrer geographischen Lage an der Landenge zwischen Wolga und Don schon im Altertum eine wichtige Handelsroute. Hier siedelten im 5. Jahrhundert v. Chr. Skythen. Im 8. und 9. Jahrhundert gehörte das Gebiet zum Reich der Chasaren, im 11. und 12. Jahrhundert hielten sich hier verschiedene Stämme und Horden auf, unter anderen die Polovcer oder die Goldene Horde, die etwa 50 km östlich von Wolgograd, am Fluss Achtuba, mit der Stadt Snamensk eines ihrer Zentren errichtete und Wolgograd seit dem Mongolensturm im 13. Jahrhundert beherrschte. Die Anfänge des russischen Wolgograds sind nicht näher beleuchtet. Als offizielles Gründungsdatum gilt aber der 2. Juli 1589, als die Stadt als Festung gegründet wurde, die Russland vor den Nomaden aus dem Süden schützen sollte. Die ursprüngliche Bezeichnung der Stadt ist Zarizyn (Царицын), aus dem Tatarischen sari su (gelbes Wasser) abgeleitet."
    String Bsp9 = "Die Abkürzungsweise mit Punkten, aber ohne Leerzeichen, ist veraltet. Es gibt aber drei Sonderfälle, in welchen dies weiterhin zulässig ist.Sonderfall: Bei der Verwendung einer Festbreitenschrift (wie etwa bei einer Schreibmaschine) darf das Leerzeichen bei Abkürzungen entfallen. Bei der Verwendung einer Proportionalschrift gilt das fehlende Leerzeichen hingegen als falsch.Beispiele: z.B., d.h., s.o., aber: z. B., d. h., s. o.Sonderfall: Bei eingebürgerten Abkürzungen, die aus allgemeiner Gewohnheit oder aus Marketinggründen nicht der aktuellen Abkürzungsschreibweise angepasst wurden.Beispiele: F.A.Z.Sonderfall: Österreich; gemäß ÖNORM waren bei manchen Abkürzungen, wie jener von „zum Beispiel“, auch folgende Schreibweisen korrekt: zB und z.B. Nach der neuesten Ausgabe muss es jedoch so geschrieben werden: z. B."    
    String[] sentences = minitest( Bsp9 , 9 )
//    String[] sentences = minitest(new File(RESOURCES_DIR + "Stz-Artikel.txt"))
    
    return null;
  }

  // wird in eclipse benötigt, damit ein "Run As Groovy Script" möglich ist (ohne Inhalt)
  // nach dem Instanzieren wird run() ausgeführt
  static main(args) {
  }

}
